import React, { Component } from 'react';
import {
  Button,
  Checkbox,
  Collapse,
  Drawer,
  Icon,
  Input,
  InputNumber,
  message,
  Modal,
  Radio,
  Select,
  Spin,
  Table,
  TimePicker,
  Tooltip
} from 'antd';
import _, { get } from 'lodash';
import PropTypes from 'prop-types';
import cn from 'classnames';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import CheckboxGroup from 'antd/lib/checkbox/Group';
import { NavLink } from 'react-router-dom';

import {
  addDetectionTask,
  addVulDetectionTask,
  getAllPortTemplates,
  getTargetList
} from '@api/task';
import { getInterfaces } from '@api/update.js';
import CheckboxSelect from '@components/checkbox-select';
import {
  CIDR_RE,
  IP_INTERVAL_RE,
  IP_RE,
  IP_V6,
  NAME_RE,
  PORT_RANGE_RE,
  PORT_RE,
  TASK_PRIORITY_MAP,
  DOMAIN_RE
} from '@util/constants';
import { actions as assetManageActions } from '@containers/asset-manage/reducer';

import EraserPng from './images/eraser.png';
import './index.less';
import {
  commonPorts,
  descriptions,
  drawerTableProps,
  titleMap,
  CIDRCountList,
  detectionMinTime
} from './constants';
import TaskLimitDate from '@components/task-limit-date';
import checkDetectionTime from '@util/checkDetectionTime';
import { withRouter } from 'react-router';
import VulStrategy from '@containers/asset-manage/components/VulStrategy';

const TextArea = Input.TextArea;
const RadioGroup = Radio.Group;

class DetectionTaskModal extends Component {
  static defaultFormState = {
    ports: commonPorts,
    portsError: '',
    portsType: 'common',
    interfacesError: '',
    speedLimit: 500,
    isCycle: false,
    priority: 'middle',
    protocol: ['icmp', 'tcp', 'udp'],
    depthDetect: true,
    connectionCount: 75000,
    connectionCountError: '',
    connectionCountStatus: 1,
    intervalTime: 1,
    intervalUnit: 'day',
    webFingerprintDetection: true,
    ignoreType: {
      whitelist: true,
      custom: false
    },
    strategyMap: {
      detectionPolicy: 'affectedComponent'
    }
  };
  static defaultState = {
    name: '',
    nameError: '',
    targetType: 'custom',
    siteQuery: {},
    ips: [],
    ipsError: '',
    ipRangeIds: '',
    locationQuery: null,
    ipInfoQuery: '',
    timing: {},
    startAt: '',
    endAt: '',
    timeRangeError: '',
    detectionTimeError: '',
    customIgnoreTarget: [],
    ignoreIpsError: '',
    selectedIpRangesKeys: [],
    ipRangesSpinning: false,
    portTemplateLoading: false,
    selectedPortTemplate: '',
    uploadingAttachment: false,
    selectedOnedaysError: '',
    protocolError: '',
    templateError: ' ',

    ...DetectionTaskModal.defaultFormState
  };

  constructor(props) {
    super(props);
    const ips = Array.isArray(props.selectedTargets) ? props.selectedTargets : [];
    this.state = {
      ...DetectionTaskModal.defaultState,
      ips: ips,
      ipRanges: [],
      ipRangesMap: {},
      connectionCountStatus: 1, // 0不限制 1自定义
      interfacesList: [], // 扫描网口
      interfaces: '',
      drawerVisible: false,
      portTemplates: [],
      portTemplatesMap: {},
      locationJsonData: [],
      isToday: false
    };
  }

  componentDidMount() {
    this.loadInterfaces();
    this.loadPortTemplates();
  }

  loadInterfaces = () => {
    getInterfaces().then(res => {
      const list = _.get(res, 'data.data.interfaces', []);
      if (!list.length) {
        this.setState({ interfacesError: '当前没有可用工作网口' });
      }
      this.setState({ interfacesList: list, interfaces: list[0] || '' });
    });
  };

  loadIpRanges = () => {
    this.setState({ ipRangesSpinning: true });
    getTargetList({
      page: 1,
      pageSize: 199
    }).then(res => {
      const ipRanges = get(res, 'data.data.list', []);
      const ipRangesMap = ipRanges.reduce((total, current = {}, index) => {
        total[current._id] = index;
        return total;
      }, {});
      this.setState({ ipRanges, ipRangesMap, ipRangesSpinning: false });
    });
  };

  loadPortTemplates = () => {
    this.setState({ portTemplateLoading: true });
    getAllPortTemplates().then(res => {
      const portTemplates = get(res, 'data.data.list', []);
      const portTemplatesMap = portTemplates.reduce((total, current = {}, index) => {
        total[current._id] = index;
        return total;
      }, {});
      this.setState({ portTemplates, portTemplatesMap, portTemplateLoading: false });
    });
  };

  // eslint-disable-next-line
  UNSAFE_componentWillReceiveProps(nextProps) {
    const { visible, selectedTargets = [], siteQuery } = nextProps;

    if (!visible) {
      return this.setState(DetectionTaskModal.defaultState);
    } else if (!this.props.visible && visible) {
      const detectionCache = nextProps[`${visible.toLowerCase()}DetectionConfig`] || {};
      const { connectionCount } = detectionCache;
      if (connectionCount) {
        detectionCache.connectionCountStatus = 1;
      } else if (connectionCount === 0) {
        detectionCache.connectionCountStatus = 0;
      }
      const interfaces = _.get(this.state, 'interfacesList[0]', '');
      return this.setState({
        ips: selectedTargets,
        siteQuery,
        ...detectionCache,
        interfaces
      });
    }
  }

  renderPort = () => {
    const { portsType, ports, portsError, templateError } = this.state;
    let portDom = null;
    if (portsType === 'common' || portsType === 'custom') {
      portDom = (
        <React.Fragment>
          <TextArea
            className="ports"
            rows={3}
            value={_.join(ports, ',')}
            onChange={this.onPortsChange}
            placeholder={descriptions.customPortsPlaceholder}
          />
          {portsError && <p className="validate-error">{portsError}</p>}
        </React.Fragment>
      );
    } else if (portsType === 'template') {
      const { selectedPortTemplate, portTemplateLoading, portTemplates } = this.state;
      portDom = (
        <div className="port-templates">
          <div className="select-wrapper">
            <label>选择模板</label>
            <Select
              optionLabelProp="title"
              dropdownClassName="tm-asset-modal-select-drawdown"
              size="small"
              value={selectedPortTemplate}
              onChange={this.onPortTemplateChange}
              loading={portTemplateLoading}
            >
              {portTemplates.map(portTemplate => (
                <Select.Option
                  title={portTemplate.name}
                  value={portTemplate._id}
                  key={portTemplate._id}
                >
                  <div className="template-item">
                    {portTemplate.name}
                    {selectedPortTemplate === portTemplate._id && <Icon type="check" />}
                  </div>
                </Select.Option>
              ))}
            </Select>
          </div>
          <TextArea className="ports" rows={3} value={_.join(ports, ',')} disabled />
          {templateError && <p className="validate-error">{templateError}</p>}
          <a href="/asset-config/port-manage" target="_blank">
            前往进行端口管理
          </a>
        </div>
      );
    }

    return (
      <>
        <div className={cn('item', 'port-title')}>
          <span className="item-title required">探测端口</span>
          <RadioGroup className="ports-type" value={portsType} onChange={this.onPortsTypeChange}>
            <Radio value="common">常用端口</Radio>
            <Radio value="custom">自定义</Radio>
            <Radio value="template">策略模板</Radio>
          </RadioGroup>
          <span className="clear" onClick={this.clearPorts}>
            <img src={EraserPng} alt="" />
            清空
          </span>
        </div>
        {portDom}
      </>
    );
  };

  renderSpeedLimit = () => (
    <div className={cn('item', 'speed-limit')}>
      <span className="item-title">
        扫描带宽
        <Tooltip title="实际扫描所产生流量会因探测目标和端口的数量而不同，您可在这里设置最大允许的扫描带宽。最大为50000Kbps">
          <Icon type="exclamation-circle" />
        </Tooltip>
      </span>
      <span className="speed-limit-input">
        <InputNumber
          min={0}
          value={this.state.speedLimit}
          max={50000}
          onChange={speedLimit => {
            if (speedLimit > 50000) {
              message.warning('扫描带宽不能大于50000,将自动设置成50000');
              return;
            }
            this.setState({ speedLimit });
          }}
        />
        <span className="unit">&nbsp;Kbps</span>
      </span>
    </div>
  );

  //渲染并发数
  renderConnectionCount = () => {
    const onChange = value => {
      if (value < 10000) {
        this.setState({
          connectionCount: value,
          connectionCountError: '配置参数不能小于10000'
        });
      } else if (value > 5000000) {
        this.setState({
          connectionCount: value,
          connectionCountError: '配置参数不能大于5000000'
        });
      } else if (value % 5000) {
        this.setState({
          connectionCount: value,
          connectionCountError: '配置参数应该是5000的倍数'
        });
      } else {
        this.setState({
          connectionCount: value,
          connectionCountError: ''
        });
      }
    };
    const errorText = this.state.connectionCountError;
    return (
      <>
        <div style={{ marginBottom: 24 }}>
          <div className={cn('item', 'connectionCount')}>
            <span className="item-title required">
              连接数/并发数
              <Tooltip
                title={
                  '请根据上层转发设备所能建立的最大连接数或者目标资产的处理性能来合理设置。设置的越小，任务执行的时间越长。范围：10000-5000000，默认值：75000。'
                }
              >
                <Icon className={'icon-question'} type="question-circle" />
              </Tooltip>
            </span>
            <Radio.Group
              onChange={e => {
                this.setState({ connectionCountStatus: e.target.value });
              }}
              value={this.state.connectionCountStatus}
            >
              <Radio value={0}>不限制</Radio>
              <Radio value={1}>自定义</Radio>
            </Radio.Group>
            {Boolean(this.state.connectionCountStatus) && (
              <InputNumber
                step={5000}
                value={this.state.connectionCount}
                onChange={onChange}
                min={10000}
                max={5000000}
              />
            )}
            &nbsp;&nbsp;
            <Button
              type="link"
              size="small"
              onClick={() => this.setState({ drawerVisible: true })}
              className={'icon-exclamation'}
            >
              连接数建议表
            </Button>
          </div>
          {errorText && <p className={'validate-error connection-error'}>{errorText}</p>}
        </div>
        {this.renderSpeedLimit()}
      </>
    );
  };

  renderTarget = () => {
    const { selectedTargets, visible: visibleKey } = this.props;
    const { targetType } = this.state;
    const selectedCount = _.get(selectedTargets, 'length');
    const isVulTask = visibleKey === 'VulDetect';
    const disabled = Boolean(selectedCount) && isVulTask;
    if (disabled) {
      const { ips, ipsError } = this.state;
      return (
        <React.Fragment>
          <TextArea
            disabled={disabled}
            className="target ips"
            value={_.join(ips, '\n')}
            rows={3}
            placeholder={descriptions.customIpsPlaceholder}
            onChange={this.onTargetsChange}
          />
          {ipsError && <p className="validate-error">{ipsError}</p>}
        </React.Fragment>
      );
    }
    if (targetType === 'custom') {
      const { ips, ipsError } = this.state;
      const { allSite, allSiteTitle } = this.props;

      return (
        <React.Fragment>
          <TextArea
            className="target ips"
            value={!allSite ? _.join(ips, '\n') : allSiteTitle}
            rows={3}
            disabled={allSite}
            placeholder={descriptions.customIpsPlaceholder}
            onChange={this.onTargetsChange}
          />
          {ipsError && <p className="validate-error">{ipsError}</p>}
        </React.Fragment>
      );
    } else if (targetType === 'ipRange') {
      const { selectedIpRangesKeys, ipRanges, ipRangesError } = this.state;
      const selectedIpRanges = _.filter(ipRanges, range =>
        _.includes(selectedIpRangesKeys, range._id)
      );
      const ips = _.join(_.flatten(_.map(selectedIpRanges, 'ips')), '\n');
      return (
        <React.Fragment>
          <TextArea
            className="target ip-ranges"
            value={ips}
            rows={3}
            placeholder={descriptions.customIpsPlaceholder}
            onChange={this.onTargetsChange}
          />
          {ipRangesError && <p className="validate-error">{ipRangesError}</p>}
        </React.Fragment>
      );
    } else {
      return null;
    }
  };

  onTargetsChange = e => {
    const value = e.target.value;
    const targets = _.split(value, '\n');
    let ipsError = value.length ? '' : '探测目标不能为空';
    let targetCount = 0;

    for (let i = 0; i < targets.length; i++) {
      if (targetCount > 131072) {
        break;
      }
      const target = targets[i];
      if (DOMAIN_RE.test(target) || IP_RE.test(target) || IP_V6.test(target)) {
        targetCount += 1;
      } else if (CIDR_RE.test(target)) {
        const range = target.split('/')[1];
        if (Number(range) < 16) {
          targetCount = Infinity;
          break;
        } else {
          targetCount += CIDRCountList[Number(range)];
        }
      } else if (IP_INTERVAL_RE.test(target, true)) {
        const ipRange = target.split('-');
        const startIPArr = ipRange[0].split('.').map(Number);
        const endIPArr = ipRange[1].split('.').map(Number);
        if (startIPArr[0] !== endIPArr[0] || endIPArr[1] !== startIPArr[1]) {
          targetCount = Infinity;
          ipsError = '起始IP和末尾IP只允许最后两位不同';
          break;
        }
        const rangeC = endIPArr[2] - startIPArr[2];
        const rangeD = endIPArr[3] - startIPArr[3];
        const ipCount = rangeC * Math.pow(2, 8) + rangeD;
        if (ipCount <= 0) {
          ipsError = '起始IP必须小于末尾IP';
          break;
        } else {
          targetCount += ipCount;
        }
      } else {
        ipsError = '探测目标格式错误';
        break;
      }
    }
    if (targetCount > 131072 && !ipsError) {
      ipsError = '探测目标不超过 131,072 个';
    }

    this.setState({ targetType: 'custom', ips: targets, ipsError });
  };

  onNameChange = e => {
    const name = e.target.value;
    let nameError = '';
    if (!name) {
      nameError = '任务名不能为空';
    } else if (name.length > 32) {
      nameError = '您输入的内容超过32个字符限制';
    } else if (!NAME_RE.test(name)) {
      nameError = '您输入的格式有误，仅支持中文、英文、数字、特殊字符 - 、— \\ _ / ：~';
    }
    this.setState({ name, nameError });
  };

  onTargetTypeChange = e => {
    const targetType = e.target.value;
    const update = { targetType };

    if (targetType === 'ipRange') {
      update.ipRangesModalVisible = true;
    }

    this.setState(update, () => {
      if (this.state.targetType === 'ipRange') {
        this.loadIpRanges();
      }
    });
  };

  clearTarget = () => {
    const clear = {
      targetType: 'custom',
      siteQuery: {},
      ips: [],
      ipsError: '',
      selectedIpRangesKeys: [],
      ipRangesSpinning: false
    };
    this.setState(clear);
  };

  onPortsChange = e => {
    const value = e.target.value;
    const ports = _.split(value, ',');
    let portsError = value.length ? '' : '探测端口不能为空';

    const formatError =
      !portsError &&
      _.some(ports, port => {
        return !PORT_RE.test(port) && !PORT_RANGE_RE.test(port);
      });

    if (formatError) {
      portsError = '探测端口格式不正确';
    }

    this.setState({ portsType: 'custom', ports, portsError });
  };

  onPortsTypeChange = e => {
    const portsType = e.target.value;

    let ports = portsType === 'common' ? commonPorts : '';
    this.setState(
      {
        ports,
        portsType,
        portsError: '',
        selectedPortTemplate: ''
      },
      this.checkMassiveScan
    );
  };

  onPortTemplateChange = value => {
    const { portTemplates, portTemplatesMap } = this.state;
    const ports = _.get(portTemplates, `${portTemplatesMap[value]}.ports`, []);
    this.setState({
      selectedPortTemplate: value,
      ports
    });
  };

  clearPorts = () => {
    this.setState({
      ports: [],
      portsError: '',
      selectedPortTemplate: ''
    });
  };

  onTimeRangeChange = (key, time) => {
    const timing = this.state.timing || {};
    let { dailyStart, dailyEnd } = timing;
    let timeRangeError = '';
    if (key === 'dailyStart') {
      dailyStart = time;
    } else {
      dailyEnd = time;
    }
    if (!dailyEnd) {
      timeRangeError = '请选择终止时间';
    }
    if (!dailyStart) {
      timeRangeError = '请选择起始时间';
    }

    if (dailyStart && dailyEnd) {
      const gap = dailyEnd - dailyStart;

      if (gap < detectionMinTime && gap > -detectionMinTime) {
        timeRangeError = '终止时间要大于起始时间30分钟以上';
      }
    }

    this.setState({ timing: { ...timing, dailyStart, dailyEnd }, timeRangeError }, () => {
      this.checkTime();
    });
  };

  onDateStartChange = startAt => {
    this.setState({ startAt }, () => {
      this.checkTime();
    });
  };

  onDateEndChange = endAt => {
    this.setState({ endAt }, () => {
      this.checkTime();
    });
  };

  checkTime = () => {
    const { timing = {}, startAt, endAt, timeRangeError } = this.state;
    if (timeRangeError) {
      return;
    }

    const hasDetectEnoughTime = checkDetectionTime({ timing, startAt, endAt });

    this.setState({
      detectionTimeError: hasDetectEnoughTime ? '' : '运行时间小于30分钟，请重新选择'
    });
  };

  onDispatchTask = async () => {
    const {
      nameError,
      portsError,
      timeRangeError,
      connectionCountError,
      ipsError,
      connectionCount,
      name,
      ports,
      interfaces,
      targetType,
      ips,
      siteQuery,
      selectedIpRangesKeys,
      ipRanges,
      startAt,
      endAt,
      timing: timeRange,
      isCycle,
      intervalTime,
      intervalUnit,
      priority,
      protocol,
      speedLimit,
      customIgnoreTarget,
      connectionCountStatus,
      portsType,
      selectedPortTemplate,
      depthDetect,
      detectionTimeError,
      webFingerprintDetection,
      ignoreType,
      selectedOnedaysError,
      strategyMap,
      templateError,
      ignoreIpsError
    } = this.state;

    const { selectedTargetsIds, allSite } = this.props;
    if (ignoreIpsError) {
      return;
    }

    const errors = {
      nameError,
      portsError,
      timeRangeError,
      connectionCountError,
      detectionTimeError,
      selectedOnedaysError,
      templateError
    };
    if (!connectionCount && connectionCount !== 0) {
      errors.connectionCountError = '连接数/并发数不能为空';
    }
    if (!name) {
      errors.nameError = '任务名称不能为空';
    }
    if (_.isEmpty(ports) && portsType !== 'template') {
      errors.portsError = '探测端口不能为空';
    }
    if (portsType === 'template' && !selectedPortTemplate) {
      errors.templateError = '请选择模板';
    } else {
      errors.templateError = '';
    }
    if (!interfaces) {
      errors.interfacesError = '扫描网口不能为空';
    } else {
      errors.interfacesError = '';
    }
    const target = {};
    switch (targetType) {
      case 'custom':
        if (ipsError) {
          errors.ipsError = ipsError;
        }
        if (_.isEmpty(ips) && !_.get(this.state, 'siteQuery.count')) {
          errors.ipsError = '探测目标不能为空';
        }
        if (!_.isEmpty(siteQuery)) {
          target.siteQuery = _.pick(siteQuery, ['description', 'query']);
        }
        if (!_.isEmpty(selectedTargetsIds)) {
          target.siteIdList = selectedTargetsIds;
        }
        if (!_.isEmpty(ips) && !allSite) {
          target.list = ips;
        }

        break;
      case 'ipRange': {
        const selectedIpRanges = _.filter(ipRanges, range =>
          _.includes(selectedIpRangesKeys, range._id)
        );
        target.list = _.flatten(_.map(selectedIpRanges, 'ips'));
        if (_.isEmpty(target.list)) {
          errors.ipRangesError = '探测目标不能为空';
        }

        target.targetGroupIdList = selectedIpRangesKeys;

        break;
      }
      default:
        return;
    }

    if (_.isEmpty(protocol)) {
      errors.protocolError = '协议类型至少勾选一个';
    }

    let timing = _.cloneDeep(timeRange);
    if (timing) {
      startAt && (timing.startAt = startAt.format('YYYY-MM-DD HH:mm:ss'));
      endAt && (timing.endAt = endAt.format('YYYY-MM-DD HH:mm:ss'));
      timing.dailyStart && (timing.dailyStart = timing.dailyStart.format('HH:mm'));
      timing.dailyEnd && (timing.dailyEnd = timing.dailyEnd.format('HH:mm'));
    }
    if (!_.isEmpty(_.pickBy(errors, Boolean))) {
      return this.setState(errors);
    }

    const payload = {
      scanType: this.props.visible,
      name,
      target: target,
      ports,
      isCycle,
      priority,
      protocol,
      speedLimit,
      timing,
      interface: interfaces,
      portsType,
      connectionCount: connectionCountStatus ? connectionCount : 0,
      depthDetect,
      webFingerprintDetection
    };
    // 解决不限制后默认返回数据为0的问题
    if (connectionCountStatus && payload.connectionCount === 0) {
      payload.connectionCount = 10000;
    }
    if (isCycle) {
      payload.intervalTime = intervalTime;
      payload.intervalUnit = intervalUnit;
    }

    if (portsType === 'template') {
      payload.selectedPortTemplate = selectedPortTemplate;
    }

    let newIgnoreType = [];

    if (ignoreType.whitelist) {
      newIgnoreType.push('whiteList');
    }
    if (ignoreType.custom) {
      payload.customIgnoreTarget = customIgnoreTarget;
      newIgnoreType.push('custom');
    }
    if (newIgnoreType.length) {
      payload.ignoreType = newIgnoreType;
    }
    if (target.siteQuery) {
      const { query } = target.siteQuery;
      if (query) {
        payload.target.siteQuery.query = JSON.stringify(query);
      }
    }
    if (this.props.visible === 'VulDetect') {
      delete payload.scanType;
      addVulDetectionTask({ ...payload, ...strategyMap })
        .then(() => {
          message.success('下发任务成功');
          // 更新下发任务配置缓存
          this.props.loadDetectionCache();
          this.props.onVisibleChange('');
        })
        .catch(error => {
          message.error(_.get(error, 'type') === 'parsed' ? error.message : '下发任务失败');
        });
    } else {
      addDetectionTask(payload)
        .then(() => {
          message.success('下发任务成功');
          // 更新下发任务配置缓存
          this.props.loadDetectionCache();
          this.props.onVisibleChange('');
        })
        .catch(error => {
          message.error(_.get(error, 'type') === 'parsed' ? error.message : '下发任务失败');
        });
    }
  };

  handleInterfacesChange = value => {
    this.setState({ interfaces: value });
  };

  // 恢复默认配置
  handleRestoreConfig = () => {
    // 探测端口、扫描网口、扫描带宽、连接数/并发数、任务类型、优先级、协议类型、操作系统深度
    this.setState({
      ...DetectionTaskModal.defaultFormState,
      interfaces: this.state.interfacesList[0] || ''
    });
  };

  handleIgnoreTypeChange = e => {
    const { ignoreType } = this.state;
    const value = e.target.value;
    const checked = e.target.checked;

    this.setState({ ignoreType: { ...ignoreType, [value]: checked } });
  };

  handleJumpWhitelist = () => {
    const { history } = this.props;
    history.push('/asset-config/white-list');
  };

  handleWebFingerChange = e => {
    const { protocol } = this.state;
    const value = e.target.checked;
    if (!protocol.includes('tcp')) {
      protocol.push('tcp');
    }
    this.setState({ webFingerprintDetection: value, protocol: [...protocol] });
  };

  render() {
    const { visible: visibleKey, selectedTargets = [], allSite } = this.props;
    const {
      addingZoomeye,
      ipRangesModalVisible,
      drawerVisible,
      interfacesList,
      interfacesError,
      detectionTimeError,
      timeRangeError,
      webFingerprintDetection,
      protocolError,
      ips
    } = this.state;
    const timeError = timeRangeError || detectionTimeError;
    const selectedCount = _.get(selectedTargets, 'length');
    const isVulTask = visibleKey === 'VulDetect';
    const isSelectVulTask = Boolean(selectedCount) && isVulTask; // 已勾选的漏洞普查任务

    const footer = [
      <Button onClick={() => this.props.onVisibleChange('')} key="0">
        取消
      </Button>,
      <Button
        onClick={this.onDispatchTask}
        key="1"
        type="primary"
        className="button-forwards"
        loading={addingZoomeye}
        disabled={allSite && _.isEmpty(ips) && !_.get(this.state, 'siteQuery.count')}
      >
        确定
      </Button>
    ];

    return (
      <div>
        <Modal
          maskClosable={false}
          className="detection-task-modal"
          visible={visibleKey}
          title={titleMap[visibleKey]}
          footer={footer}
          onCancel={() => this.props.onVisibleChange('')}
          mask={!ipRangesModalVisible}
          destroyOnClose
          width={620}
        >
          <div className="detection-restore-btn">
            <Button type="link" onClick={this.handleRestoreConfig}>
              恢复默认配置
            </Button>
            <Tooltip
              title={`下发${
                isVulTask ? '1DAY' : ''
              }探测任务的弹框，会自动保留您上一次任务设置的探测端口、扫描网口、扫描带宽、连接数/并发数、任务类型、优先级、协议类型、操作系统深度的信息，可点击将以上配置项的参数内容恢复到系统默认参数。`}
            >
              <Icon type="question-circle" />
            </Tooltip>
          </div>
          {isSelectVulTask && (
            <div className={'number'}>
              此次检测资产数
              <span>{selectedCount}个</span>
            </div>
          )}
          <div className={'item'}>
            <span className="item-title required">任务名称</span>
            <Input
              placeholder={descriptions.taskNamePlaceholder}
              value={this.state.name}
              onChange={this.onNameChange}
            />
          </div>
          {this.state.nameError && (
            <p className="validate-error name-error">{this.state.nameError}</p>
          )}
          <div className={cn('item', 'goal-title')}>
            <span className="item-title required">
              探测目标
              <Tooltip title={descriptions.targetLimit}>
                <Icon type="exclamation-circle" />
              </Tooltip>
            </span>
            {!isSelectVulTask && (
              <>
                <RadioGroup
                  className="goal-type"
                  value={this.state.targetType}
                  onChange={this.onTargetTypeChange}
                >
                  <Radio value="custom">自定义</Radio>
                  <Radio value="ipRange">选择目标组</Radio>
                </RadioGroup>
                <span className="clear" onClick={this.clearTarget}>
                  <img src={EraserPng} alt="" />
                  清空
                </span>
              </>
            )}
          </div>
          {this.renderTarget()}
          {!isSelectVulTask && this.renderPort()}
          {isVulTask && (
            <VulStrategy
              changeCallback={(strategyMap, errorMsg) =>
                this.setState({ strategyMap, selectedOnedaysError: errorMsg })
              }
            />
          )}
          <div className={cn('item', 'interface-title')}>
            <span className="item-title required">扫描网口</span>
            <Select
              onChange={this.handleInterfacesChange}
              defaultValue={interfacesList[0]}
              getPopupContainer={triggerNode => triggerNode.parentNode}
            >
              {interfacesList.map((item, index) => {
                if (!index) {
                  return (
                    <Select.Option value={item} key={item}>
                      默认
                    </Select.Option>
                  );
                }
                return (
                  <Select.Option value={item} key={item}>
                    {`${item}`}
                  </Select.Option>
                );
              })}
            </Select>
          </div>
          {interfacesError && <p className="validate-error">{interfacesError}</p>}
          {this.renderConnectionCount()}
          <div className={cn('item', 'task-type')}>
            <span className="item-title">任务类型</span>
            <RadioGroup
              className="task-type-group"
              value={this.state.isCycle ? 'true' : 'false'}
              onChange={e => this.setState({ isCycle: e.target.value === 'true' })}
            >
              <Radio value="false">单次</Radio>
              <Radio value="true">周期</Radio>
            </RadioGroup>
          </div>
          {this.state.isCycle && (
            <div className="cycle-config">
              <InputNumber
                min={0}
                value={this.state.intervalTime}
                onChange={value => {
                  let intervalTime = value;
                  if (intervalTime <= 1) {
                    intervalTime = 1;
                  } else {
                    intervalTime = Math.floor(intervalTime);
                  }
                  return this.setState({ intervalTime });
                }}
              />
              <Select
                value={this.state.intervalUnit}
                onChange={intervalUnit => this.setState({ intervalUnit })}
                getPopupContainer={triggerNode => triggerNode.parentNode}
              >
                <Select.Option value="hour">时</Select.Option>
                <Select.Option value="day">日</Select.Option>
                <Select.Option value="week">周</Select.Option>
                <Select.Option value="month">月</Select.Option>
              </Select>
            </div>
          )}
          <div className={cn('item', 'date-range')}>
            <span className="item-title">
              任务执行时限
              <Tooltip title={descriptions.dateLimit}>
                <Icon type="exclamation-circle" />
              </Tooltip>
            </span>
            <TaskLimitDate
              onDateStartChange={this.onDateStartChange}
              onDateEndChange={this.onDateEndChange}
            />
          </div>
          <div className={cn('item', 'time-range')}>
            <span className="item-title">
              每日允许时间段
              <Tooltip title={descriptions.timeLimit}>
                <Icon type="exclamation-circle" />
              </Tooltip>
            </span>
            <div className="time-picker-range">
              <TimePicker
                className="daily-start"
                placeholder="开始时间"
                format="HH:mm"
                value={this.state.timing.dailyStart}
                onChange={time => this.onTimeRangeChange('dailyStart', time)}
                getPopupContainer={triggerNode => triggerNode.parentNode}
              />
              &nbsp;&nbsp;
              <TimePicker
                className="daily-end"
                placeholder="结束时间"
                format="HH:mm"
                value={this.state.timing.dailyEnd}
                onChange={time => this.onTimeRangeChange('dailyEnd', time)}
                getPopupContainer={triggerNode => triggerNode.parentNode}
              />
            </div>
          </div>
          {timeError && <p className="validate-error time-range-error">{timeError}</p>}
          <div className={cn('item', 'pripority')}>
            <span className="item-title">优先级</span>
            <RadioGroup
              className="priority-group"
              value={this.state.priority}
              onChange={e => this.setState({ priority: e.target.value })}
            >
              {Object.keys(TASK_PRIORITY_MAP).map(key => (
                <Radio key={key} value={key}>
                  {TASK_PRIORITY_MAP[key]}
                </Radio>
              ))}
            </RadioGroup>
          </div>

          <div className={cn('item', 'web-finger-detect')}>
            <span className="item-title">
              Web指纹探测
              <Tooltip title="系统会针对探测出来的具有http、https服务的端口进一步执行Web指纹探测。任务耗时会更长。">
                <Icon type="exclamation-circle" />
              </Tooltip>
            </span>
            <Checkbox checked={webFingerprintDetection} onChange={this.handleWebFingerChange} />
          </div>

          <div className={cn('item', 'protocol')}>
            <span className="item-title required">协议类型</span>
            <CheckboxGroup
              className="protocol-group"
              value={this.state.protocol}
              onChange={protocol =>
                this.setState({
                  protocol,
                  protocolError: _.isEmpty(protocol) ? '协议类型至少勾选一个' : ''
                })
              }
            >
              <Checkbox value="icmp">ICMP</Checkbox>
              <Checkbox value="udp">UDP</Checkbox>
              <Checkbox disabled={webFingerprintDetection} value="tcp">
                TCP
              </Checkbox>
            </CheckboxGroup>
            <br />
          </div>
          {protocolError && <p className="validate-error">{protocolError}</p>}
          <div className={cn('item', 'pripority')}>
            <span className="item-title">国产化识别</span>
            <Checkbox.Group
              className="Checkbox-group"
              disabled
              options={[
                { label: '系统软件', value: '0' },
                { label: '数据库', value: '1' },
                { label: '操作系统', value: '2' },
                { label: '硬件设备', value: '3' }
              ]}
              defaultValue={['0', '1', '2', '3']}
            />
            <NavLink className="Checkbox-button" to={'/knowledge-base/localized'} target="_blank">
              查看清单识别
            </NavLink>
          </div>
          <Collapse className="advance">
            <Collapse.Panel key="advance" header="高级配置">
              {isVulTask && Boolean(selectedCount) && this.renderPort()}
              <div className={cn('item', 'depth-detect')}>
                <span className="item-title">
                  操作系统深度探测
                  <Tooltip title="系统会对目标进行深度探测，识别到更多的操作系统信息，但也会影响扫描速度，任务耗时会更长。">
                    <Icon type="exclamation-circle" />
                  </Tooltip>
                </span>
                <Checkbox
                  checked={this.state.depthDetect}
                  onChange={e =>
                    this.setState({
                      depthDetect: e.target.checked
                    })
                  }
                />
              </div>
              <div className={cn('ignore-ips')}>
                <span className="item-title">禁扫目标</span>
                <Checkbox
                  value={'whitelist'}
                  defaultChecked={true}
                  onChange={this.handleIgnoreTypeChange}
                >
                  启用
                </Checkbox>
                <a onClick={this.handleJumpWhitelist}>去配置</a>
              </div>
            </Collapse.Panel>
          </Collapse>
          <Drawer
            width={800}
            title={
              <span className={'drawer-title'}>
                连接数建议表（本表依据实验室环境测试结果，仅作为推荐参数使用）
              </span>
            }
            placement="right"
            onClose={() => this.setState({ drawerVisible: false })}
            visible={drawerVisible}
          >
            <Table {...drawerTableProps} />
          </Drawer>
        </Modal>
        <Modal
          maskClosable={false}
          title="选择目标组"
          visible={ipRangesModalVisible}
          destroyOnClose={true}
          className={cn('ip-range-select', 'no-header-bottom-lines', 'bottom-center', 'padding-24')}
          onCancel={() => this.setState({ ipsType: 'custom', ipRangesModalVisible: false })}
          onOk={() => this.setState({ ipRangesModalVisible: false })}
        >
          <Spin tip="加载中" spinning={this.state.ipRangesSpinning}>
            <CheckboxSelect
              placeholder="请输入关键词搜索"
              onChange={selectedIpRangesKeys => this.setState({ selectedIpRangesKeys })}
              options={this.state.ipRanges}
              selected={this.state.selectedIpRangesKeys}
            />
          </Spin>
          <a className="to-target-manage" href="/asset-config/target-manage" target="_blank">
            前往进行目标组管理
          </a>
        </Modal>
      </div>
    );
  }
}

DetectionTaskModal.propTypes = {
  visible: PropTypes.string,
  onVisibleChange: PropTypes.func,
  selectedTargets: PropTypes.array,
  onSuccess: PropTypes.func,
  modules: PropTypes.array,
  form: PropTypes.object,
  siteQuery: PropTypes.object,
  zoomeyeDetectionConfig: PropTypes.object,
  loadDetectionCache: PropTypes.func,
  history: PropTypes.object,
  selectedTargetsIds: PropTypes.array,
  allSite: PropTypes.Boolean,
  allSiteTitle: PropTypes.string
};

const mapStateToProps = state => {
  return {
    user: get(state, 'auth.user', {}),
    modules: get(state, 'auth.cert.modules', []),
    zoomeyeDetectionConfig: get(state, 'assetManage.zoomeyeDetectionConfig', {}),
    vuldetectDetectionConfig: get(state, 'assetManage.vuldetectDetectionConfig', {})
  };
};

const mapDispatchToProps = dispatch => {
  return {
    ...bindActionCreators(assetManageActions, dispatch)
  };
};

export default withRouter(
  connect(
    mapStateToProps,
    mapDispatchToProps
  )(DetectionTaskModal)
);
